package com.xx.sign.util;

import com.google.common.collect.Lists;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author fanjj
 * @date 2017/10/26
 */
public class SignToken {
    public static final String SECURITY_VERSION_STRING = "v";//版本
    public static final String TIME_STAMP = "timestamp";//时间戳
    public static final String APP_KEY = "app_key";//app标识
    public static final String APP_SECRET = "app_secret";//app秘钥
    public static final String SIGN = "sign";//签名

    private static final String INPUT_CHARSET = "utf-8";
    private static final int TIME_LINE = 1800;// 超时限度,30分钟
    private static final String SAFE_VERSION_KEY = "1.0";//安全协议版本

    private static void validateParameter(Map<String, String> map, String appSecret, String sign) throws Exception {
        if (StringUtils.isBlank(map.get(TIME_STAMP))) {
            throw new Exception("Missing Timestamp!");
        }
        if (StringUtils.isBlank(map.get(SECURITY_VERSION_STRING))) {
            throw new Exception("Missing Security Version!");
        }
        if (StringUtils.isBlank(map.get(APP_KEY))) {
            throw new Exception("Missing App Key!");
        }
        long now = System.currentTimeMillis();
        if (Math.abs(now - Long.parseLong(map.get(TIME_STAMP))) / 1000 >= TIME_LINE) {
            //throw new Exception("Timestamp is not Correct!");
        }
        if (StringUtils.isBlank(sign)) {
            throw new Exception("Missing Sign!");
        }
        if (StringUtils.isBlank(appSecret)) {
            throw new Exception("Missing App Secret!");
        }
    }

    public static String getToken(Map<String, String> parameterMap, String appSecret, String sign) throws Exception {
        validateParameter(parameterMap, appSecret, sign);
        byte[] preSign = (appSecret + createLinkString(parameterMap) + appSecret).getBytes(INPUT_CHARSET);
        return DigestUtils.md5Hex(preSign);
    }

    /**
     * 签名验证
     *
     * @param parameterMap
     * @param appSecret    秘钥
     * @param sign         签名结果
     * @throws Exception
     */
    public static void validate(Map<String, String> parameterMap, String appSecret, String sign) throws Exception {
        String token = getToken(parameterMap, appSecret, sign);
        if (!StringUtils.equals(sign, token)) {
            throw new Exception("Sign is not Correct!");
        }
    }

    /**
     * 把数组所有元素排序，并按照“参数=参数值”的模式拼接成字符串
     *
     * @param params 需要排序并参与字符拼接的参数组
     * @return 拼接后字符串
     */
    private static String createLinkString(Map<String, String> params) {
        List<String> keys = Lists.newArrayList(params.keySet());
        Collections.sort(keys);
        StringBuilder builder = new StringBuilder(1024);
        int size = keys.size();
        for (int i = 0; i < size; i++) {
            builder.append(keys.get(i));
            builder.append(params.get(keys.get(i)) == null ? "" : params.get(keys.get(i)));
        }
        return builder.toString();
    }
}
